module PNEngine
  class Petrinet < ActiveRecord::Base
    include Resource::InstanceMethods
    extend Resource::ClassMethods
    
    has_many :transitions, :dependent => :destroy
    has_many :arcs, :dependent => :destroy
    has_many :places, :dependent => :delete_all
    
    #finds transition by pnml id
    def find_transition(pid)
      self.transitions.find(:first, :conditions => ["pid = ?", pid])
    end
    
    before_create :label_petrinet
    def label_petrinet
      self.name = "Anonymous (#{self.id})" if self.name.blank?
    end
    
    after_create :prepare_caching
    def prepare_caching
      transitions.each do |t|
        t.has_incoming_places = (t.incoming_places.size > 0)
        t.has_inhibitor = (t.arcs.select{|a|a.kind_of?(PNEngine::InhibitorArc)}.size > 0)
        t.save!
      end
    end
    
    def url(options = {})
      u = "/petrinets/#{id}"
      u = Merb::Config[:path_prefix] + u if Merb::Config[:path_prefix]
      u
    end
    
    def to_pnml
      pnml_doc = REXML::Document.new
      pnml = pnml_doc.add_element('pnml')
      net = pnml.add_element('net', {'id' => pid, 'type' => 'CP-net'})
      
      #add name if specified
      if name
        pname = net.add_element('name')
        ptext = pname.add_element('text')
        ptext.text = name
      end
      
      #add transitions
      if transitions
        transitions.each do |transition|
          net.add_element(transition.to_pnml(true))
        end
      end
      
      #add places
      if places
        places.each do |place|
          net.add_element(place.to_pnml(true))
        end
      end
      
      #add arcs
      if arcs
        arcs.each do |arc|
          net.add_element(arc.to_pnml(true))
        end
      end
      
      #add xml declaration as REXML::Document does not automatically writes one
      pnml_doc << REXML::XMLDecl.default
      
      #output as string
      output = ''
      pnml_doc.write(output, 2, true)
    end
  end
end
